home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume9 / cn_pexpire < prev    next >
Encoding:
Text File  |  1990-01-04  |  54.9 KB  |  1,798 lines

  1. Newsgroups: comp.sources.misc
  2. From: jrp@rducky.UUCP (JIM PICKERING)
  3. organization: Technical Solutions, Inc.
  4. subject: v09i097: pexpire for Cnews
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 9, Issue 97
  8. Submitted-by: jrp@rducky.UUCP (JIM PICKERING)
  9. Archive-name: cn_pexpire
  10.  
  11. Here is a new version of pexpire that I have modified for Cnews.
  12. Since it was originally copyrighted by Dave Taylor, I have enclosed his
  13. correspondence allowing me to post it.
  14.  
  15. jim
  16.  
  17.  
  18. Jim Pickering c/o Technical Solutions    || (north) ..csustan!polyslo!rducky!jrp 
  19. P.O. Box 1045                || (south) ..sdsu!polyslo!rducky!jrp 
  20. Arroyo Grande, CA 93421            || (south) ..csun!polyslo!rducky!jrp
  21. (805) 473-1037                || (east)  ..csufres!polyslo!rducky!jrp
  22.  
  23. ------------------------------------------------------------------------------
  24. Jim,
  25.     You are more than welcome to distribute a new version of my
  26. Pexpire program.. thanks for modifying it to work with C news too!
  27.  
  28.                 Ciao!
  29.                         -- Dave Taylor
  30. Intuitive Systems
  31. Mountain View, California
  32.  
  33. taylor@limbo.intuitive.com    or   {uunet!}{decwrl,apple}!limbo!taylor
  34. ------------------------------------------------------------------------------
  35. #! /bin/sh
  36. # This is a shell archive.  Remove anything before this line, then unpack
  37. # it by saving it into a file and typing "sh file".  To overwrite existing
  38. # files, type "sh file -c".  You can also feed tncli as standard input via
  39. # unshar, or by typing "sh <file", e.g..  If tncli archive is complete, you
  40. # will see the following message at the end:
  41. #        "End of archive 1 (of 1)."
  42. # Contents:  MANIFEST Makefile README README.CNEWS bpexpire.1
  43. #   cpexpire.1 dopexpire pexpire.batch pexpire.c pexpire.defs
  44. #   pexpire.h pexplist
  45. # Wrapped by jrp@rducky on Tue Jan  2 21:12:59 1990
  46. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  47. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  48.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  49. else
  50. echo shar: Extracting \"'MANIFEST'\" \(486 characters\)
  51. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  52. X   File Name        Archive #    Description
  53. X-----------------------------------------------------------
  54. X MANIFEST                   1    This shipping list
  55. X Makefile                   1    
  56. X README                     1    
  57. X README.CNEWS               1    
  58. X bpexpire.1                 1    
  59. X cpexpire.1                 1    
  60. X dopexpire                  1    
  61. X pexpire.batch              1    
  62. X pexpire.c                  1    
  63. X pexpire.defs               1    
  64. X pexpire.h                  1    
  65. X pexplist                   1    
  66. END_OF_FILE
  67. if test 486 -ne `wc -c <'MANIFEST'`; then
  68.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  69. fi
  70. # end of 'MANIFEST'
  71. fi
  72. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  73.   echo shar: Will not clobber existing file \"'Makefile'\"
  74. else
  75. echo shar: Extracting \"'Makefile'\" \(3310 characters\)
  76. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  77. X#
  78. X#    Makefile for the pexpire program
  79. X#      
  80. X#  by Dave Taylor, Hewlett-Packard Co.
  81. X#  Cnews modifications by Jim Pickering (jrp@rducky)
  82. X
  83. XSHELL    =    /bin/sh
  84. XCFILES   =    pexpire.c
  85. XHEADERS  =    pexpire.h
  86. XOBJS     =    pexpire.o
  87. X
  88. X# our executable ... if you change this, you'll have to edit dopexpire (Cnews)
  89. XPROGNAME =    pexpire
  90. X
  91. X# our doexpire(8) replacement for Cnews
  92. XBATCHNAME=    dopexpire
  93. X
  94. X# Bnews man directory
  95. XMANDIR    =    /usr/man/local/man1
  96. X# Cnews man directory
  97. XMANDIR    =    /usr/man/local/man8
  98. X
  99. X# Bnews install directory
  100. XNEWSDIR    =    /usr/lib/news
  101. X# Cnews install directory ... if you change this, you'll have to edit dopexpire
  102. XNEWSDIR    =    /usr/lib/newsbin/expire
  103. X
  104. X# Cnews pexplist install directory ... if you change this, you'll have to edit
  105. X# dopexpire
  106. XLISTDIR    =    /usr/lib/news
  107. X
  108. X# the next is probably the only thing you'll need to locally customize
  109. X# to reflect the top level location of the netnews source on your 
  110. X# machine ... Bnews
  111. X
  112. XNEWS_SRC =    /usr/local/src/news.2.11
  113. X
  114. XINCLUDEDIR  =   -I${NEWS_SRC}
  115. XLIBS     =       -lPW
  116. XRM       =    rm -f
  117. X
  118. X# use for BNEWS
  119. XCFLAGS   =     -O ${INCLUDEDIR}
  120. X# use for CNEWS
  121. XCFLAGS   =     -O -DCNEWS
  122. X
  123. X# your favorite C compiler
  124. XCC       =    /bin/cc
  125. XCC       =    /bin/ccc
  126. X
  127. X${PROGNAME}: ${OBJS}
  128. X    ${CC} -o ${PROGNAME} -s ${OBJS} ${LIBS}
  129. X
  130. Xpexpire.c: pexpire.h
  131. Xpexpire.o: pexpire.c
  132. X
  133. Xclean:
  134. X    ${RM} ${OBJS} LINT.OUT core $(PROGNAME) tempxxx
  135. X
  136. Xlint: LINT.OUT
  137. X
  138. XLINT.OUT: ${CFILES}
  139. X    lint ${DEFINE} ${INCLUDEDIR} ${CFILES} ${LIBS} > LINT.OUT
  140. X
  141. Xshar:
  142. X    ${RM} Part* MANIFEST
  143. X    makekit -oMANIFEST Makefile README* cpexpire.1 bpexpire.1 pexpire.c pexpire.defs pexpire.h pexpire.batch dopexpire pexplist
  144. X    compress Part*
  145. X
  146. Xrealclean: shar clean
  147. X    ${RM} MANIFEST Makefile README* cpexpire.1 bpexpire.1 pexpire.c pexpire.defs pexpire.h pexpire.batch dopexpire pexplist
  148. X
  149. Xbnewsinstall: $(PROGNAME)
  150. X    mv $(PROGNAME) $(NEWSDIR)
  151. X    chmod 0750 $(NEWSDIR)/$(PROGNAME)
  152. X    chown news $(NEWSDIR)/$(PROGNAME)
  153. X    chgrp news $(NEWSDIR)/$(PROGNAME)
  154. X    cp pexpire.defs $(NEWSDIR)
  155. X    chown news $(NEWSDIR)/pexpire.defs
  156. X    chgrp news $(NEWSDIR)/pexpire.defs
  157. X    cp bpexpire.1 $(MANDIR)/pexpire.1
  158. X    chown bin $(MANDIR)/pexpire.1
  159. X    chgrp bin $(MANDIR)/pexpire.1
  160. X    chmod 0444 $(MANDIR)/pexpire.1
  161. X    @echo
  162. X    @echo "\tInstall pexpire.batch and"
  163. X    @echo "\t\tput an entry for $(PROGNAME) in /usr/lib/crontab"
  164. X    @echo
  165. X
  166. Xbnewsuninstall:
  167. X    ${RM} $(NEWSDIR)/$(PROGNAME)
  168. X    ${RM} $(NEWSDIR)/pexpire.defs
  169. X    ${RM} $(MANDIR)/pexpire.1
  170. X
  171. Xcnewsinstall: $(PROGNAME) $(BATCHNAME)
  172. X    mv $(PROGNAME) $(NEWSDIR)
  173. X    chmod 0775 $(NEWSDIR)/$(PROGNAME)
  174. X    chown bin $(NEWSDIR)/$(PROGNAME)
  175. X    chgrp bin $(NEWSDIR)/$(PROGNAME)
  176. X    cp $(BATCHNAME) $(NEWSDIR)
  177. X    chmod 0775 $(NEWSDIR)/$(BATCHNAME)
  178. X    chown bin $(NEWSDIR)/$(BATCHNAME)
  179. X    chgrp bin $(NEWSDIR)/$(BATCHNAME)
  180. X    cp pexplist $(LISTDIR)/pexplist
  181. X    chown bin $(LISTDIR)/pexplist
  182. X    chgrp bin $(LISTDIR)/pexplist
  183. X    chmod 0444 $(LISTDIR)/pexplist
  184. X    cp cpexpire.1 $(MANDIR)/pexpire.8
  185. X    chown bin $(MANDIR)/pexpire.8
  186. X    chgrp bin $(MANDIR)/pexpire.8
  187. X    chmod 0444 $(MANDIR)/pexpire.8
  188. X    ${RM} $(MANDIR)/dopexpire.8
  189. X    ln $(MANDIR)/pexpire.8 $(MANDIR)/dopexpire.8
  190. X    @echo
  191. X    @echo "Put a similar entry for $(BATCHNAME) in /usr/lib/crontab:"
  192. X    @echo "\t44 0 * * * /bin/su news -c '/usr/lib/newsbin/expire/dopexpire'"
  193. X    @echo
  194. X
  195. Xcnewsuninstall:
  196. X    ${RM} $(NEWSDIR)/$(PROGNAME)
  197. X    ${RM} $(NEWSDIR)/$(BATCHNAME)
  198. X    ${RM} $(LISTDIR)/pexplist
  199. X    ${RM} $(MANDIR)/pexpire.8
  200. X    ${RM} $(MANDIR)/dopexpire.8
  201. END_OF_FILE
  202. if test 3310 -ne `wc -c <'Makefile'`; then
  203.     echo shar: \"'Makefile'\" unpacked with wrong size!
  204. fi
  205. # end of 'Makefile'
  206. fi
  207. if test -f 'README' -a "${1}" != "-c" ; then 
  208.   echo shar: Will not clobber existing file \"'README'\"
  209. else
  210. echo shar: Extracting \"'README'\" \(852 characters\)
  211. sed "s/^X//" >'README' <<'END_OF_FILE'
  212. X
  213. X         Additional Administrative Notes for Pexpire
  214. X
  215. X              August 29th, 1988
  216. X
  217. X  It is strongly recommended that you read the man page for the
  218. X  netnews expire() command, studying the '-e' and '-E' options,
  219. X  then read the pexpire() man page distributed with the pexpire
  220. X  package.
  221. X
  222. X  From there, you need to edit the Makefile to ensure that it
  223. X  is pointing at the right source directory for netnews, then
  224. X  edit the file "pexpire.h". 
  225. X
  226. X  You should notice that pexpire.h expects that the netnews
  227. X  "defs.h" file is available -- it grabs the default expiration
  228. X  times from that file (see the extensively commented "pexpire.h"
  229. X  file for details).
  230. X
  231. X  Finally, this is a first distribution, so there might very well
  232. X  be problems and non-portabilities.  If you come across anything,
  233. X  please drop me a note.
  234. X
  235. X                    Dave Taylor
  236. X                    
  237. X  taylor@hplabs.hp.com
  238. END_OF_FILE
  239. if test 852 -ne `wc -c <'README'`; then
  240.     echo shar: \"'README'\" unpacked with wrong size!
  241. fi
  242. # end of 'README'
  243. fi
  244. if test -f 'README.CNEWS' -a "${1}" != "-c" ; then 
  245.   echo shar: Will not clobber existing file \"'README.CNEWS'\"
  246. else
  247. echo shar: Extracting \"'README.CNEWS'\" \(1093 characters\)
  248. sed "s/^X//" >'README.CNEWS' <<'END_OF_FILE'
  249. Xsubject:    Notes for Pexpire for Cnews
  250. Xdate:        December 30, 1989
  251. Xfrom:        Jim Pickering (jrp@rducky)
  252. X
  253. X
  254. X
  255. XIt is strongly recommended that you read the man page for
  256. Xthe Cnews expire(8) command, studying the expire list line
  257. Xoptions, then read the cpexpire.1 man page distributed with
  258. Xthe pexpire package.  Note that dopexpire() does not use
  259. X/usr/lib/news/explist.
  260. X
  261. XYou may need to edit the Makefile, edit the file
  262. X"pexpire.h", edit the file "pexplist", and edit the file
  263. X"dopexpire", paying particular attention to lines after '#
  264. XYOU MAY WANT TO EDIT THE FOLLOWING'.  To install, as root
  265. Xdo a 'make cnewsinstall'.
  266. X
  267. XCredit-where-credit-is-due department:
  268. XDave Taylor (taylor@limbo.intuitive.com) originally wrote
  269. Xpexpire.  I made some relatively minor modifications so that
  270. Xit would run under Cnews.  His copyright stands.  Dopexpire
  271. Xis just a doexpire ripoff from Cnews, written by Henry Spencer
  272. Xand Geoff Collyer at U. of Toronto.  The man page is a
  273. Xcombination of both Cnews' expire(8) and Dave's pexpire(1) man
  274. Xpages.
  275. X
  276. XIf you come across problems and non-portabilities, please
  277. Xdrop me a note.
  278. X
  279. Xjim
  280. END_OF_FILE
  281. if test 1093 -ne `wc -c <'README.CNEWS'`; then
  282.     echo shar: \"'README.CNEWS'\" unpacked with wrong size!
  283. fi
  284. # end of 'README.CNEWS'
  285. fi
  286. if test -f 'bpexpire.1' -a "${1}" != "-c" ; then 
  287.   echo shar: Will not clobber existing file \"'bpexpire.1'\"
  288. else
  289. echo shar: Extracting \"'bpexpire.1'\" \(8460 characters\)
  290. sed "s/^X//" >'bpexpire.1' <<'END_OF_FILE'
  291. X.TH PEXPIRE 1M local
  292. X.ad b
  293. X.SH NAME
  294. Xpexpire - expire netnews groups based on local readership
  295. X.SH SYNOPSIS
  296. X.B pexpire
  297. X[-cgrov] 
  298. X[-e cmd] 
  299. X[-a N] 
  300. X[-h N] 
  301. X[-H N] 
  302. X.SH HP-UX COMPATIBILITY
  303. X.TP 10
  304. XLevel:
  305. XHP-UX/CONTRIBUTED
  306. X.TP
  307. XOrigin:
  308. XHewlett-Packard
  309. X.SH DESCRIPTION
  310. X.I Pexpire
  311. Xis intended to offer a finer granularity in the expiration of
  312. Xnetnews articles on a multi-user machine.  The philosophy behind
  313. Xit is that there are typically a large set of newsgroups that
  314. Xno-one on the machine reads, which makes them very likely targets
  315. Xfor shorter expiration times.  
  316. X.PP
  317. XThis program allows you to do exactly that \(em it lets you set
  318. Xdefault expiration times for all groups on your machine depending
  319. Xon if they are subscribed to or not, then checks each users
  320. X".newsrc" to ascertain this information.  The finaly output of
  321. Xthe program is a set of \fIexpire\fR commands suitable for automatic execution
  322. Xout of cron.
  323. X.PP
  324. XThe flags understood are:
  325. X.TP 8
  326. X.B \-a n      
  327. XSet default history expire value to 'n'. 
  328. X.sp
  329. XThere are actually three
  330. Xflags to do with expiration dates that \fIpexpire\fR understands:
  331. Xthe `-a' flag to set the default history expire value, and the `-h'
  332. Xand `-H' flags to set a bracketing for when the `-E' flag needs to
  333. Xbe output.
  334. X.sp
  335. XThat doesn't make any sense, I'm sure, so let's look at it this
  336. Xway: the \fIexpire\fR program uses two different expiration
  337. Xdates, one for when the article should be removed, and another
  338. Xfor when the entry should be removed from the ``history'' file.
  339. XWith that in mind, the `-a' flag sets the default history expire
  340. Xdate for the `history' file, and the `-h' and `-H' flags set up
  341. Xthe window (eg. the program checks:
  342. X.ft CW
  343. X.nf
  344. X
  345. X    min-hist-expire < current-expire < max-hist-expire
  346. X
  347. X.fi
  348. X.ft R
  349. Xfor each \fIexpire\fR command output).  Please see the 
  350. X\fIexpire\fR man page for more information on the `-e'
  351. Xand `-E' flags.
  352. X.sp
  353. XThe default value for this is 28 days.
  354. X.TP 8
  355. X.B \-c        
  356. XMake the groupname list comma separated, rather than space
  357. Xseparated.  This is a cosmetic change to the output, but you
  358. Xmight have a version of \fIexpire\fR that wants one or the
  359. Xother explicitly.
  360. X.TP 8
  361. X.B \-e cmd    
  362. XUses 'cmd' for output rather than the default expire program
  363. X.sp
  364. XThe default set to ``/usr/local/lib/news/expire''.
  365. X.TP 8
  366. X.B \-g n      
  367. XForces `n' or less groups output per command.
  368. XThis is because some versions of \fIexpire\fR have a limit as
  369. Xto the number of groups they'll accept for expiration in a single
  370. Xinvocation.
  371. X.sp
  372. XThe default is 50 groups.
  373. X.TP 8
  374. X.B \-h n      
  375. XSet the default minimum history expire value to 'n'  (see `-a' above)
  376. X.sp
  377. XThe current default is set to 14 days.
  378. X.TP 8
  379. X.B \-H n      
  380. XSet the default maximum history expire value to 'n'  (see `-a' above)
  381. X.sp
  382. XThe current default is set to 28 days.
  383. X.TP 8
  384. X.B \-r        
  385. XTakes user id 0 account ".newsrc" files into account \(em a lot of
  386. Xsites have multiple roots, with each having their usual home
  387. Xdirectory (eg. the one for their non-administrative account).
  388. XIn a situation like this there is no reason to pay the extra
  389. Xoverhead of checking their ".newsrc" file twice.
  390. X.sp
  391. XThe default is to ignore user id 0 accounts.
  392. X.TP 8
  393. X.B \-o        
  394. XForces one-group-per-line output format.
  395. X.sp
  396. XThe default is to use the value of the `-g' flag for groups per 
  397. Xoutput line.
  398. X.TP 8
  399. X.B \-v        
  400. XTurns on verbose output mode.
  401. X.PP
  402. XIn addition, the program allows the administrator to define a file
  403. Xthat contains default expiration times for groups or sets of 
  404. Xgroups.  This file is called ``pexpire.defaults'' and the format
  405. Xit expects is:
  406. X.nf
  407. X
  408. X    pattern    +expire     -expire
  409. X
  410. X.fi
  411. XWhere the pattern can be any reguler expression accepted by the
  412. Xregexp(3c) package, the +expire is the number of days to expire
  413. Xthe group if people are reading it, and -expire is the number
  414. Xof days to expire the group if no-one is reading it currently.
  415. X.SH EXAMPLES
  416. XThe configuration we have locally for ourselves has the following
  417. X"pexpire.defaults" file:
  418. X.nf
  419. X.ft CW
  420. X
  421. X  #
  422. X  # This is the "pexpire" default expiration times file.  The 
  423. X  # format of this file is:
  424. X  #
  425. X  #   <regular expression>    <+expire>     <-expire>
  426. X  #
  427. X  # where <+expire> is the expiration date for groups that are 
  428. X  # currently read by people on this machine, <-expire> are for 
  429. X  # those that are unread, and <regular expression> is any regular 
  430. X  # expression as per regexp(3c).
  431. X  #
  432. X  # It is recommended that you have ".*" as the first expression so 
  433. X  # that you can set the default expiration for all groups.  The 
  434. X  # processing order of this information is: 
  435. X  #      for each pattern read in this file:
  436. X  #        for each group in the active file:
  437. X  #          if the pattern matches, set the dates accordingly.
  438. X  #
  439. X  # this means that the patterns "^comp.*" and "source" in that 
  440. X  # order would result in "comp.unix.sources" having the source 
  441. X  # expire times.
  442. X  #
  443. X  # NOTE: never lead an expression with an asterisk -- assume all 
  444. X  #       patterns are unrooted, and use '^' to get them left rooted 
  445. X  #       if you want to
  446. X  .*                    14      1
  447. X  ^hp.*                 30      15
  448. X  ^comp.*               10      2
  449. X  ^talk.*               7       1
  450. X  ^soc.*                7       1
  451. X  ^news.*               14      2
  452. X  source                14      7
  453. X  test                  1       1
  454. X  comp.mail.elm         56      28
  455. X
  456. X.ft R
  457. X.fi
  458. XNotice that the first regular expression, ``.*'', gives us the default
  459. Xexpiration time for all groups on our machine, then we modify it according
  460. Xto local interests and needs.  Also notice that patterns default to being
  461. Xable to `float', that is, ``source'' matches all groups that have the word
  462. Xsource in their names, whether left, right, or not rooted at all.
  463. X.sp
  464. XAdditionally, we invoke the following shell script via cron:
  465. X.nf
  466. X.ft CW
  467. X
  468. X  : Use /bin/sh
  469. X  
  470. X  # expire news using pexpire()
  471. X  # script written by Rob Sartin, HP  (sartin@hplabs.hp.com) 
  472. X
  473. X  expire_script="/tmp/expire$$"
  474. X  trap 'rm -f $expire_script' 0 1 2 3 15
  475. X  
  476. X  # display our disk space utilization before the command ...
  477. X
  478. X  echo "Expiring old news"
  479. X  echo "\\nBefore:"
  480. X  bdf
  481. X  
  482. X  # get the netnews home directory by fiddling /etc/passwd:
  483. X
  484. X  eval `awk -F: "/^netnews:/"' { printf "LIBDIR=%s;\\n", $6 }' \\
  485. X     < /etc/passwd`
  486. X  
  487. X  # create the new expire script
  488. X
  489. X  rm -f ${expire_script}
  490. X  ${LIBDIR}/pexpire > ${expire_script} 2>/dev/null
  491. X  chmod 0755 ${expire_script}
  492. X
  493. X  # and execute it:
  494. X
  495. X  ${expire_script}
  496. X
  497. X  # finally, output disk space utilization after the command
  498. X
  499. X  echo "\\nAfter:"
  500. X  bdf
  501. X
  502. X  # and we're done.
  503. X
  504. X  exit 0
  505. X
  506. X.ft R
  507. X.fi
  508. XNote that you can have a minimal script by having the following
  509. Xsequence instead, if you choose:
  510. X.ft CW
  511. X.nf
  512. X
  513. X  : Use /bin/sh
  514. X
  515. X  PEXPIRE=/usr/local/lib/news/pexpire
  516. X  TMPFILE=/tmp/expire.$$
  517. X
  518. X  $PEXPIRE > $TMPFILE 
  519. X
  520. X  sh $TMPFILE
  521. X
  522. X  exit 0
  523. X
  524. X.fi
  525. X.ft R
  526. XThough the former is recommended.
  527. X.PP
  528. XAlso, you can test out the pexpire program to see what it thinks
  529. Xthe expiration time of a specific group is, for example, by a
  530. Xsequence like:
  531. X.nf
  532. X.ft CW
  533. X
  534. X  % pexpire -o -e expire | grep \fIgroup you're interested in\fR
  535. X
  536. X.ft R
  537. X.fi
  538. XFor example:
  539. X.nf
  540. X.ft CW
  541. X
  542. X  % pexpire -o -e expire | grep soc.singles
  543. X
  544. X  expire -e 7 -E 28 -n soc.singles
  545. X
  546. X.ft R
  547. X.fi
  548. XThis tells us that the group is to be expired in 7 days, but that
  549. Xthe actual article entries are to remain in the netnews history
  550. Xfile for 28 days.
  551. X.PP
  552. XWe can also find out what user ``.newsrc'' files are 
  553. Xchecked with:
  554. X.nf
  555. X.ft CW
  556. X
  557. X  % pexpire > /dev/null
  558. X
  559. X  Checking against ".newsrc" for the following users:
  560. X          sartin taylor jin markc
  561. X
  562. X.ft R
  563. X.fi
  564. Xor, with the `-v' verbose option turned on:
  565. X.nf
  566. X.ft CW
  567. X
  568. X  % pexpire -v | sed '/^$/,$d'
  569. X
  570. X  Read 511 groups out of the active file.
  571. X  Checked against 10 patterns in the default-expire file.
  572. X  Checking against .newsrc for user "sartin"
  573. X  Checking against .newsrc for user "taylor"
  574. X  Checking against .newsrc for user "jin"
  575. X  Checking against .newsrc for user "markc"
  576. X  
  577. X.ft R
  578. X.fi
  579. X.SH AUTHOR
  580. XDave Taylor, Hewlett-Packard Company  (taylor\s-1@\s+1hplabs.hp.com)
  581. X.SH FILES
  582. X.nf
  583. X.if n .ta 26
  584. X.if t .ta 20
  585. X/etc/passwd    for accounts to check ".newsrc" files
  586. X$USER/.newsrc    for each account on the machine, to check
  587. X$NETNEWS    usually ``/usr/local/lib/news''
  588. X$NETNEWS/active    Where the netnews active file lives
  589. X$NETNEWS/expire    The `real' \fIexpire\fR command
  590. X$NETNEWS/pexpire.default    home for the ``pexpire.default'' file
  591. X/bin/sh    valid login shell for user
  592. X/bin/csh    valid login shell for user
  593. X/bin/ksh    valid login shell for user
  594. X/bin/rsh    valid login shell for user
  595. X.SH SEE\ ALSO
  596. Xexpire(1)
  597. END_OF_FILE
  598. if test 8460 -ne `wc -c <'bpexpire.1'`; then
  599.     echo shar: \"'bpexpire.1'\" unpacked with wrong size!
  600. fi
  601. # end of 'bpexpire.1'
  602. fi
  603. if test -f 'cpexpire.1' -a "${1}" != "-c" ; then 
  604.   echo shar: Will not clobber existing file \"'cpexpire.1'\"
  605. else
  606. echo shar: Extracting \"'cpexpire.1'\" \(3939 characters\)
  607. sed "s/^X//" >'cpexpire.1' <<'END_OF_FILE'
  608. X.\" =()<.ds a @<NEWSARTS>@>()=
  609. X.ds a /usr/spool/news
  610. X.\" =()<.ds b @<NEWSBIN>@>()=
  611. X.ds b /usr/lib/newsbin
  612. X.\" =()<.ds c @<NEWSCTL>@>()=
  613. X.ds c /usr/lib/news
  614. X.\" =()<.ds m @<NEWSMASTER>@>()=
  615. X.ds m postmaster
  616. X.ad b
  617. X.TH PEXPIRE 8 local
  618. X.SH NAME
  619. Xpexpire, dopexpire - expire netnews groups based on local readership
  620. X.SH SYNOPSIS
  621. X.B \*b/expire/pexpire
  622. X[
  623. X.B \-s
  624. X] 
  625. X[
  626. X.B \-v
  627. X] 
  628. X[
  629. X.B \-e N
  630. X] 
  631. X[
  632. X.B \-r N
  633. X] 
  634. X[
  635. X.B \-p N
  636. X] 
  637. X[
  638. X.B \-E N
  639. X] 
  640. X[
  641. X.B \-R N
  642. X] 
  643. X[
  644. X.B \-P N
  645. X] 
  646. X.br
  647. X.B \*b/expire/doexpire
  648. Xexpireoptions
  649. X.SH DESCRIPTION
  650. X.I Pexpire
  651. Xis intended to offer a finer granularity in the expiration of
  652. Xnetnews articles on a multi-user machine.  The philosophy behind
  653. Xit is that there are typically a large set of newsgroups that
  654. Xno-one on the machine reads, which makes them very likely targets
  655. Xfor shorter expiration times.  
  656. X.PP
  657. XThis program allows you to do exactly that \(em it lets you set
  658. Xdefault expiration times for all groups on your machine depending
  659. Xon if they are subscribed to or not, then checks each users
  660. X".newsrc" to ascertain this information.  The finaly output of
  661. Xthe program is a set of \fIexpire\fR lines suitable for automatic execution
  662. Xby \fIdopexpire\fR out of cron.
  663. X.PP
  664. XThe flags understood are:
  665. X.TP 8
  666. X.B \-e N      
  667. XSet expirey period of all read news groups to 'N'. 
  668. XThe default value for this is 14 days.
  669. X.TP 8
  670. X.B \-r N      
  671. XSet retention period of all read news groups to 'N'. 
  672. XThe default value for this is 14 days.
  673. X.TP 8
  674. X.B \-p N      
  675. XSet purge period of all read news groups to 'N'. 
  676. XThe default value for this is 14 days.
  677. X.TP 8
  678. X.B \-E N      
  679. XSet expirey period of all unread news groups to 'N'. 
  680. XThe default value for this is 1 day.
  681. X.TP 8
  682. X.B \-R N      
  683. XSet retention period of all unread news groups to 'N'. 
  684. XThe default value for this is 1 day.
  685. X.TP 8
  686. X.B \-P N      
  687. XSet purge period of all unread news groups to 'N'. 
  688. XThe default value for this is 1 day.
  689. X.TP 8
  690. X.B \-s        
  691. XTakes user id 0 account ".newsrc" files into account \(em a lot of
  692. Xsites have multiple roots, with each having their usual home
  693. Xdirectory (eg. the one for their non-administrative account).
  694. XIn a situation like this there is no reason to pay the extra
  695. Xoverhead of checking their ".newsrc" file twice.
  696. X.sp
  697. XThe default is to ignore user id 0 accounts.
  698. X.TP 8
  699. X.B \-v        
  700. XTurns on verbose output mode.
  701. X.PP
  702. XWe can find out what user ``.newsrc'' files are 
  703. Xchecked with:
  704. X.nf
  705. X.ft CW
  706. X
  707. X.B 
  708. X  % \*b/expire/pexpire -v | sed '/^$/,$d'
  709. X
  710. X  Read 511 groups out of the active file.
  711. X  Checked against 10 patterns in the default-expire file.
  712. X  Checking against .newsrc for user "sartin"
  713. X  Checking against .newsrc for user "taylor"
  714. X  Checking against .newsrc for user "jin"
  715. X  Checking against .newsrc for user "markc"
  716. X  
  717. X.ft R
  718. X.fi
  719. X.PP
  720. X.I Dopexpire
  721. Xchecks whether another \fIdopexpire\fR is running,
  722. Xchecks that there is enough disk space for expiry and archiving,
  723. Xbuilds the temporary expire list using \fIpexpire\fR and \fI\*c/pexplist\fR,
  724. Xinvokes \fIexpire\fR with any \fIexpireoptions\fR given and with
  725. Xtemporary expire list as the control file,
  726. Xand reports any difficulties by sending mail to \fI\*m\fR.
  727. XThis is usually better than just running \fIexpire\fR directly.
  728. XIf space is adequate for archiving but persistently inadequate for the
  729. Xtemporaries needed for history rebuilding, \fIdopexpire\fR reports this
  730. Xand invokes \fIexpire\fR with the \fB\-r\fR option.
  731. X.SH AUTHOR
  732. XDave Taylor, Hewlett-Packard Company  (taylor\s-1@\s+1hplabs.hp.com)
  733. X.br
  734. XModified for Cnews by Jim Pickering   (jrp\s-1@\s+1rducky)
  735. X.SH FILES
  736. X.nf
  737. X.if n .ta 26
  738. X.if t .ta 20
  739. X/etc/passwd    for accounts to check ".newsrc" files
  740. X$USER/.newsrc    for each account on the machine, to check
  741. X\*c/active    where the netnews active file lives
  742. X\*c/pexplist    where the system default pexpire list lives
  743. X\*c/LOCKexpire    lock file
  744. X\*c/L.$$    lock file
  745. X/bin/sh    valid login shell for user
  746. X/bin/csh    valid login shell for user
  747. X/bin/ksh    valid login shell for user
  748. X/bin/rsh    valid login shell for user
  749. X.SH SEE ALSO
  750. Xexpire(8), doexpire(8)
  751. END_OF_FILE
  752. if test 3939 -ne `wc -c <'cpexpire.1'`; then
  753.     echo shar: \"'cpexpire.1'\" unpacked with wrong size!
  754. fi
  755. # end of 'cpexpire.1'
  756. fi
  757. if test -f 'dopexpire' -a "${1}" != "-c" ; then 
  758.   echo shar: Will not clobber existing file \"'dopexpire'\"
  759. else
  760. echo shar: Extracting \"'dopexpire'\" \(2449 characters\)
  761. sed "s/^X//" >'dopexpire' <<'END_OF_FILE'
  762. X#! /bin/sh
  763. X# dopexpire - overall administration for expire using pexpire
  764. X
  765. X# =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  766. X. ${NEWSCONFIG-/usr/lib/news/bin/config}
  767. X
  768. XPATH=$NEWSCTL/bin:$NEWSBIN/expire:$NEWSBIN:$NEWSPATH ; export PATH
  769. Xumask $NEWSUMASK
  770. X
  771. Xlock="$NEWSCTL/LOCKexpire"
  772. Xltemp="$NEWSCTL/L.$$"
  773. X
  774. X# retention, expire, and purge defaults for 'all' groups that we may have
  775. X# missed with pexpire or our default file
  776. Xretention_default="0"
  777. Xexpirey_default="0"
  778. Xpurge_default="0"
  779. X
  780. X#sysadmin supplied expiration defaults
  781. Xdefaults_file="$NEWSCTL/pexplist"
  782. X
  783. X# expire list generated by pexpire
  784. Xpexpire_list="/tmp/pexpire$$"
  785. Xpexpire_tmp="/tmp/pexptmp$$"
  786. X
  787. X# expired and bounds strings for expire(8)
  788. Xexpire_string="/expired/\tx\t14\t-"
  789. Xbounds_string="/bounds/\tx\t0-1-90\t-"
  790. X
  791. Xecho $$ >$ltemp
  792. Xtrap "rm -f $ltemp ; exit 0" 0 1 2 15
  793. Xif newslock $ltemp $lock
  794. Xthen
  795. X    trap "rm -f $ltemp $lock ; exit 0" 0 1 2 15
  796. Xelse
  797. X    echo "$0: expire apparently already running" | mail "$NEWSMASTER"
  798. X    exit 1
  799. Xfi
  800. X
  801. Xif test " `spacefor 1 archive`" -le 0
  802. Xthen
  803. X    echo "$0: not enough space for archiving" | mail "$NEWSMASTER"
  804. X    exit 1
  805. Xfi
  806. X
  807. Xcd $NEWSCTL
  808. Xropt=-r
  809. Xfor counter in x x x x        # four tries
  810. Xdo
  811. X    size="`sizeof history history.pag history.dir`"
  812. X    if test " `spacefor $size control`" -gt 0
  813. X    then
  814. X        ropt=
  815. X        break
  816. X    fi
  817. X    sleep 600        # and hope it will improve
  818. Xdone
  819. Xif test " $ropt" = " -r"
  820. Xthen
  821. X    echo "$0: short of space for temporaries, resorting to \`expire -r'" |
  822. X                            mail "$NEWSMASTER"
  823. Xfi
  824. X
  825. Xtrap "rm -f $pexpire_list $ltemp $lock ; exit 0" 0 1 2 15
  826. X
  827. Xecho $expire_string > $pexpire_list
  828. Xecho $bounds_string >> $pexpire_list
  829. Xif test -s $defaults_file
  830. Xthen
  831. X    cat $defaults_file >> $pexpire_list
  832. Xfi
  833. Xtrap "rm -f $pexpire_list $pexpire_tmp $ltemp $lock ; exit 0" 0 1 2 15
  834. Xpexpire -E 0.5 -R 0.5 -P 0.5 -e 14 -r 14 -p 14 > $pexpire_tmp 2>/tmp/doex$$
  835. Xif test -s /tmp/doex$$
  836. Xthen
  837. X    (echo 'pexpire problems:' ; cat /tmp/doex$$ ) | mail "$NEWSMASTER"
  838. X    rm -f /tmp/doex$$
  839. X    exit 1
  840. Xfi
  841. X# sort in reverse order so groups at top of hierarchy don't expire lower
  842. X# groups, i.e. rec.humor may affect rec.humor.funny if before
  843. Xsort -r $pexpire_tmp >> $pexpire_list
  844. Xrm -f $pexpire_tmp
  845. Xtrap "rm -f $pexpire_list $ltemp $lock ; exit 0" 0 1 2 15
  846. Xecho "all\tx\t$retention_default-$expirey_default-$purge_default\t-" >> $pexpire_list
  847. Xexpire $ropt $* $pexpire_list 2>/tmp/doex$$
  848. Xif test -s /tmp/doex$$
  849. Xthen
  850. X    (echo 'expire problems:' ; cat /tmp/doex$$ ) | mail "$NEWSMASTER"
  851. X    rm -f /tmp/doex$$
  852. X    exit 1
  853. Xfi
  854. Xrm -f /tmp/doex$$
  855. Xexit 0
  856. END_OF_FILE
  857. if test 2449 -ne `wc -c <'dopexpire'`; then
  858.     echo shar: \"'dopexpire'\" unpacked with wrong size!
  859. fi
  860. chmod +x 'dopexpire'
  861. # end of 'dopexpire'
  862. fi
  863. if test -f 'pexpire.batch' -a "${1}" != "-c" ; then 
  864.   echo shar: Will not clobber existing file \"'pexpire.batch'\"
  865. else
  866. echo shar: Extracting \"'pexpire.batch'\" \(446 characters\)
  867. sed "s/^X//" >'pexpire.batch' <<'END_OF_FILE'
  868. X# Use /bin/sh
  869. X# expire news using pexpire()
  870. X# script written by Rob Sartin, HP (sartin@hplabs.hp.com)
  871. Xexpire_script="/tmp/expire$$"
  872. Xtrap 'rm -f $expire_script' 0 1 2 3 15
  873. X
  874. X# display our disk space utilization before the command ...
  875. X
  876. XPEXPIRE=/usr/lib/news/pexpire
  877. X
  878. X# create the new expire script
  879. X
  880. X${PEXPIRE} > ${expire_script} 2>/dev/null
  881. Xchmod 0750 ${expire_script}
  882. X
  883. X# and execute it:
  884. X
  885. X${expire_script} > /dev/null 2>&1
  886. X
  887. X# and we're done.
  888. Xexit 0
  889. END_OF_FILE
  890. if test 446 -ne `wc -c <'pexpire.batch'`; then
  891.     echo shar: \"'pexpire.batch'\" unpacked with wrong size!
  892. fi
  893. chmod +x 'pexpire.batch'
  894. # end of 'pexpire.batch'
  895. fi
  896. if test -f 'pexpire.c' -a "${1}" != "-c" ; then 
  897.   echo shar: Will not clobber existing file \"'pexpire.c'\"
  898. else
  899. echo shar: Extracting \"'pexpire.c'\" \(21446 characters\)
  900. sed "s/^X//" >'pexpire.c' <<'END_OF_FILE'
  901. X/**                pexpire.c            **/
  902. X
  903. X/** This program is designed to set the expire dates of newsgroups according
  904. X    to whether they are read locally or not.  The idea is that it is easy
  905. X    to go into users .newsrc files and compile an overall list of who reads
  906. X    what groups, then 1-day-expire those groups that no-one is reading.
  907. X
  908. X    This hinges on the availability of other local machines to serve as
  909. X    archives for various groups, as well as the understanding of the 
  910. X    local users that subscribing to a new newsgroup will more than likely
  911. X    net you almost *no* new articles -- but will allow the news to flow
  912. X    in normally and then gradually build up to a more reasonable level.
  913. X
  914. X    (C) Copyright 1988 Dave Taylor
  915. X
  916. X    ***************************************************************************
  917. X    **  Permission is granted for unlimited modification, use, and dist-     **
  918. X    **  ribution, except that this software may not be sold for profit       **
  919. X    **  directly nor as part of any software package.  This software is made **
  920. X    **  available with no warranty of any kind, express or implied.          **
  921. X    ***************************************************************************
  922. X
  923. X**/
  924. X
  925. X#include <stdio.h>
  926. X#include <pwd.h>
  927. X
  928. X#include "pexpire.h"
  929. X
  930. X#define ROOT_UID    0                 /* who's root? */
  931. X
  932. X#define MAX_GROUPS    1024            /* should be sufficient */
  933. X
  934. X#define SLEN        128
  935. X
  936. X#define COLON        ':'
  937. X
  938. X#ifndef TRUE
  939. X# define TRUE        1
  940. X# define FALSE        0
  941. X#endif
  942. X
  943. X/** some easy to read and use macro functions **/
  944. X
  945. X#define whitespace(c)    (c == ' ' || c == '\t')
  946. X#define matches(re,pat)    (regex(re, pat) != NULL)
  947. X
  948. X#define plural(n)    (n == 1 ? "" : "s")
  949. X
  950. X/** and data structures/global variables for the program **/
  951. X
  952. Xstruct group_rec {
  953. X    char     *name;
  954. X    int      is_read;
  955. X#ifndef CNEWS
  956. X    int      read_expire;
  957. X    int      unread_expire;
  958. X#endif
  959. X       };
  960. X
  961. Xchar *login_shells[] = { "/bin/sh", "/bin/csh", "/bin/ksh", "/bin/rsh", "" };
  962. X
  963. Xstruct group_rec groups[MAX_GROUPS];
  964. X
  965. Xint group_count = 0,                /** total number of groups  **/
  966. X    verbose = FALSE,                /** lots of output?         **/
  967. X#ifndef CNEWS
  968. X    comma_separated = TRUE,         /** output list format        **/
  969. X    groups_per_cmd,                 /**  .. and more too        **/
  970. X
  971. X    min_history_expire,             /** for the expire() cmd    **/
  972. X    max_history_expire,             /**     "   "               **/
  973. X    default_history_expire,         /**     "   "            **/
  974. X
  975. X    output_one_per_line = FALSE,    /** final output format     **/
  976. X#endif
  977. X    include_root = FALSE;           /** include root .newsrc?   **/
  978. X
  979. X#ifndef CNEWS
  980. Xchar *prog_name,                    /** program name for errors **/
  981. X     expire_cmd[SLEN];              /** expire cmd we'll use    **/
  982. X#else
  983. Xchar *prog_name;                    /** program name for errors **/
  984. Xdouble    read_retention_period,
  985. X    read_purge_period,
  986. X    read_expirey_period,
  987. X    unread_retention_period,
  988. X    unread_purge_period,
  989. X    unread_expirey_period;
  990. X#endif
  991. X
  992. X/** forward definitions and other stuff to keep LINT a happy clam   **/
  993. X
  994. Xchar *regcmp(), *regex(), *strcpy(), *strcat(), *strchr(), *malloc();
  995. Xvoid    exit(), perror(), qsort();
  996. X
  997. X/** The algorithm that we'll be using here is:
  998. X
  999. X     1. Read in the active file to get a list of all newsgroups available
  1000. X
  1001. X     2. Go through the ``EXPIRE_DEFAULTS'' file (bnews version) to set initial
  1002. X        expiration dates (typically by high level groups -- it's left rooted).
  1003. X        This file typically has two sets of numbers, the first being for groups
  1004. X        that are being actively read, the second being for those that are
  1005. X        not.  For example:
  1006. X
  1007. X             soc.*    24    1
  1008. X
  1009. X        would set any soc.* group to a 24 day expire if read, and a 1 day
  1010. X        expire if not.
  1011. X
  1012. X     3. Then, for each user of the system:
  1013. X
  1014. X            if they have a .newsrc,
  1015. X            tag as 'read' any group that the user subscribes to
  1016. X     
  1017. X     4. Sort the newsgroups by expiration date (bnews version), then output a
  1018. X        shell script suitable for automatic execution (bnews version) or output
  1019. X        an expire list file for expire(1) (cnews version) ...
  1020. X
  1021. X**/
  1022. X
  1023. Xmain(argc, argv)
  1024. Xchar *argv[];
  1025. X{
  1026. X    extern char *optarg;
  1027. X    int c;
  1028. X
  1029. X    /** first off let's grab the program name for error messages **/
  1030. X
  1031. X    prog_name = *argv;
  1032. X
  1033. X    /** initialize some values that can be changed by the user **/
  1034. X#ifndef CNEWS
  1035. X    groups_per_cmd = DEFAULT_GROUPS_PER_LINE;
  1036. X
  1037. X    max_history_expire = DEFAULT_MAX_HISTORY_EXPIRE;
  1038. X    min_history_expire = DEFAULT_MIN_HISTORY_EXPIRE;
  1039. X
  1040. X    default_history_expire = DEFAULT_HISTORY_EXPIRE;
  1041. X
  1042. X    (void) strcpy(expire_cmd, EXPIRE);
  1043. X
  1044. X    /** now process the starting arguments **/
  1045. X
  1046. X    while ((c = getopt(argc, argv, "a:ch:H:e:g:rov")) != EOF) {
  1047. X#else
  1048. X    read_retention_period = READ_RETENTION_DEFAULT;
  1049. X    read_purge_period = READ_PURGE_DEFAULT;
  1050. X    read_expirey_period = READ_EXPIREY_DEFAULT;
  1051. X    unread_retention_period = UNREAD_RETENTION_DEFAULT;
  1052. X    unread_purge_period = UNREAD_PURGE_DEFAULT;
  1053. X    unread_expirey_period = UNREAD_EXPIREY_DEFAULT;
  1054. X    while ((c = getopt(argc, argv, "r:e:p:R:E:P:sv")) != EOF) {
  1055. X#endif
  1056. X      switch (c) {
  1057. X
  1058. X#ifndef CNEWS
  1059. X        case 'a' : default_history_expire = atoi(optarg);
  1060. X               break;
  1061. X
  1062. X        case 'c' : comma_separated = TRUE;
  1063. X               break;
  1064. X
  1065. X        case 'e' : (void) strcpy(expire_cmd, optarg);    
  1066. X               break;
  1067. X
  1068. X        case 'g' : groups_per_cmd = atoi(optarg);
  1069. X               break;
  1070. X
  1071. X        case 'h' : min_history_expire = atoi(optarg);
  1072. X               break;
  1073. X
  1074. X        case 'H' : max_history_expire = atoi(optarg);
  1075. X               break;
  1076. X
  1077. X        case 'r' : include_root = TRUE;
  1078. X               break;
  1079. X
  1080. X        case 'o' : output_one_per_line = TRUE;
  1081. X               break;
  1082. X
  1083. X        case 'v' : verbose = TRUE;
  1084. X               break;
  1085. X
  1086. X        default  : (void) fprintf(stderr,
  1087. X   "\nUsage: %s [-a n] [-c] [-e cmd] [-g] [-h n] [-H n] [-r] [-o] [-v]\n", 
  1088. X                  prog_name);
  1089. X               (void) fprintf(stderr,"\nWhere:\n");
  1090. X               (void) fprintf(stderr,
  1091. X   "   -a n  \tset default history expire value to 'n' (see the man page)\n");
  1092. X               (void) fprintf(stderr,
  1093. X   "         \t(the current default is set to %d day%s)\n", 
  1094. X                      DEFAULT_HISTORY_EXPIRE, 
  1095. X                  plural(DEFAULT_HISTORY_EXPIRE));
  1096. X               (void) fprintf(stderr,
  1097. X   "   -c    \tmake the groupname list comma separated, rather than space\n");
  1098. X               (void) fprintf(stderr,
  1099. X   "   -e cmd\tuses 'cmd' for output rather than the default expire program\n");
  1100. X               (void) fprintf(stderr,
  1101. X   "         \t(current default set to \"%s\")\n", EXPIRE);
  1102. X               (void) fprintf(stderr,
  1103. X   "   -g n  \tforces `n' or less groups output per command (default = %d)\n",
  1104. X                  DEFAULT_GROUPS_PER_LINE);
  1105. X               (void) fprintf(stderr,
  1106. X   "   -h n  \tset the default minimum history expire value to 'n'\n");
  1107. X               (void) fprintf(stderr,
  1108. X   "         \t(the current default is set to %d day%s)\n", 
  1109. X                      DEFAULT_MIN_HISTORY_EXPIRE, 
  1110. X                  plural(DEFAULT_MIN_HISTORY_EXPIRE));
  1111. X               (void) fprintf(stderr,
  1112. X   "   -H n  \tset the default maximum history expire value to 'n'\n");
  1113. X               (void) fprintf(stderr,
  1114. X   "         \t(the current default is set to %d day%s)\n", 
  1115. X                      DEFAULT_MAX_HISTORY_EXPIRE, 
  1116. X                  plural(DEFAULT_MAX_HISTORY_EXPIRE));
  1117. X               (void) fprintf(stderr,
  1118. X   "   -r    \ttakes UID 0 account .newsrc files into account\n");
  1119. X               (void) fprintf(stderr,
  1120. X   "   -o    \tforces one-group-per-line output format\n");
  1121. X               (void) fprintf(stderr,
  1122. X   "   -v    \tturns on verbose output mode\n\n");
  1123. X               exit(0);
  1124. X#else
  1125. X        case 's' : include_root = TRUE;
  1126. X               break;
  1127. X
  1128. X        case 'v' : verbose = TRUE;
  1129. X               break;
  1130. X
  1131. X        case 'r' : read_retention_period = atof(optarg);
  1132. X               sscanf(optarg,"%lg",&read_retention_period);
  1133. X               break;
  1134. X
  1135. X        case 'p' : read_purge_period = atof(optarg);
  1136. X               sscanf(optarg,"%lg",&read_purge_period);
  1137. X               break;
  1138. X
  1139. X        case 'e' : read_expirey_period = atof(optarg);
  1140. X               sscanf(optarg,"%lg",&read_expirey_period);
  1141. X               break;
  1142. X
  1143. X        case 'R' :
  1144. X               sscanf(optarg,"%lg",&unread_retention_period);
  1145. X               break;
  1146. X
  1147. X        case 'P' :
  1148. X               sscanf(optarg,"%lg",&unread_purge_period);
  1149. X               break;
  1150. X
  1151. X        case 'E' :
  1152. X               sscanf(optarg,"%lg",&unread_expirey_period);
  1153. X               break;
  1154. X
  1155. X        default  : (void) fprintf(stderr, "\nUsage: %s [-r n] [-e n] [-p n] [-R n] [-E n] [-P n] [-s] [-v]\n", prog_name);
  1156. X               (void) fprintf(stderr,"\nWhere:\n");
  1157. X               (void) fprintf(stderr, "\t-r n\tset retention period for read news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", READ_RETENTION_DEFAULT);
  1158. X               (void) fprintf(stderr, "\t-e n\tset expirey period for read news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", READ_EXPIREY_DEFAULT);
  1159. X               (void) fprintf(stderr, "\t-p n\tset purge period for read news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", READ_PURGE_DEFAULT);
  1160. X               (void) fprintf(stderr, "\t-R n\tset retention period for unread news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", UNREAD_RETENTION_DEFAULT);
  1161. X               (void) fprintf(stderr, "\t-E n\tset expirey period for unread news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", UNREAD_EXPIREY_DEFAULT);
  1162. X               (void) fprintf(stderr, "\t-P n\tset purge period for unread news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", UNREAD_PURGE_DEFAULT);
  1163. X               (void) fprintf(stderr, "\t-s\ttakes UID 0 account .newsrc files into account\n");
  1164. X               (void) fprintf(stderr, "\t-v\tturns on verbose output mode\n\n");
  1165. X               exit(0);
  1166. X#endif
  1167. X      }
  1168. X    }
  1169. X    
  1170. X    /** next let's read in the netnews active file **/
  1171. X
  1172. X    read_active_file();
  1173. X
  1174. X    /** read in the EXPIRE_DEFAULTS file and set default expires **/
  1175. X#ifndef CNEWS
  1176. X    set_default_expiration_dates();
  1177. X#endif
  1178. X    /** check each user for a .newsrc and mark groups subscribed **/
  1179. X
  1180. X    check_each_user();
  1181. X
  1182. X    /** whip through a quick resort by expiration time **/
  1183. X#ifndef CNEWS
  1184. X    sort_groups_by_expiration();
  1185. X#endif
  1186. X    /** and finally output the script that we can execute **/
  1187. X
  1188. X    output_script();
  1189. X
  1190. X    /** and we're done **/
  1191. X
  1192. X    return(0);
  1193. X}
  1194. X
  1195. Xread_active_file()
  1196. X{
  1197. X    /** this routine reads in the active file, sorts it, and 
  1198. X        returns.  It is assumed that it always works - if something
  1199. X        fails it will exit from here..
  1200. X    **/
  1201. X
  1202. X    int  compare();
  1203. X
  1204. X    FILE *fd;
  1205. X    char buffer[SLEN];
  1206. X    register int  i;
  1207. X    
  1208. X    if ((fd = fopen(ACTIVE_FILE, "r")) == NULL) {
  1209. X      (void) fprintf(stderr,"%s: cannot open active file '%s':\n",
  1210. X          prog_name, ACTIVE_FILE);
  1211. X      perror("fopen");
  1212. X      exit(1);
  1213. X    }
  1214. X
  1215. X    while (fgets(buffer, SLEN, fd) != NULL) {
  1216. X
  1217. X      /** get just the first word ... **/ 
  1218. X
  1219. X      for (i=0; ! whitespace(buffer[i]); i++) ;
  1220. X      buffer[i] = '\0';
  1221. X
  1222. X      if ((groups[group_count].name = malloc((unsigned)(i+1))) == NULL) {
  1223. X         (void) fprintf(stderr,"%s: couldn't malloc memory for group '%s'\n",
  1224. X            prog_name, buffer);
  1225. X        perror("malloc");
  1226. X        exit(1);
  1227. X      }
  1228. X
  1229. X      /** now load up the new record and increment our counter **/
  1230. X
  1231. X      (void) strcpy(groups[group_count].name, buffer);
  1232. X      groups[group_count].is_read = FALSE;
  1233. X#ifndef CNEWS
  1234. X      groups[group_count].read_expire = DEFAULT_READ_EXPIRE;
  1235. X      groups[group_count].unread_expire = DEFAULT_UNREAD_EXPIRE;
  1236. X#endif
  1237. X
  1238. X      group_count++;
  1239. X
  1240. X      /** and on to the next one... **/
  1241. X    }
  1242. X    
  1243. X    (void) fclose(fd);
  1244. X
  1245. X    qsort(groups, (unsigned) group_count, 
  1246. X          sizeof (struct group_rec), compare);
  1247. X
  1248. X    if (verbose)
  1249. X      (void) printf("Read %d group%s out of the active file.\n",
  1250. X          group_count, plural(group_count)); 
  1251. X}
  1252. X
  1253. X#ifndef CNEWS
  1254. Xset_default_expiration_dates()
  1255. X{
  1256. X    /** this routine is responsible for reading in the default
  1257. X        expire file and setting the default expiration dates on
  1258. X        all of the groups in memory.   If there is no file or it
  1259. X        is impossible to get to, then the defaults indicated in
  1260. X        this program will be used for all groups.
  1261. X
  1262. X        The format of the file is quite simple:
  1263. X
  1264. X            <regular expression> < tab > <+expire> <tab> <-expire>
  1265. X
  1266. X        where +expire is the expiration time if people are reading
  1267. X        the group, and -expire is if they're not.  The regular
  1268. X        expression format is that of regex(3c), so you can have
  1269. X        structures such as "^comp.*" and so on.
  1270. X    **/
  1271. X
  1272. X    FILE *fd;
  1273. X    char  buffer[SLEN], *regular_expression;
  1274. X    int   read_expire, unread_expire;
  1275. X    register int i, count = 0;
  1276. X
  1277. X    if ((fd = fopen(EXPIRE_DEFAULTS, "r")) == NULL) {
  1278. X      (void) fprintf(stderr,"%s: Couldn't read file '%s'\n", 
  1279. X          prog_name, EXPIRE_DEFAULTS);
  1280. X      (void) fprintf(stderr,
  1281. X          "(Using default expirations: read = %d, unread = %d)\n",
  1282. X          DEFAULT_READ_EXPIRE, DEFAULT_UNREAD_EXPIRE);
  1283. X      perror("fopen");
  1284. X      (void) fprintf(stderr,"---\n");
  1285. X
  1286. X      /** now spin through setting all expire dates accordingly **/
  1287. X
  1288. X      for (i=0; i < group_count; i++) {
  1289. X        groups[i].read_expire = DEFAULT_READ_EXPIRE;
  1290. X        groups[i].unread_expire = DEFAULT_UNREAD_EXPIRE;
  1291. X      }
  1292. X
  1293. X      return;
  1294. X    }
  1295. X
  1296. X    /** if we've gotten here we've got the file open and ready
  1297. X        to work with... **/
  1298. X
  1299. X    while (fgets(buffer, SLEN, fd) != NULL) {
  1300. X
  1301. X       if (buffer[0] == '#' || strlen(buffer) < 3) continue;
  1302. X
  1303. X      (void) sscanf(buffer, "%*s %d %d", &read_expire, &unread_expire);
  1304. X
  1305. X      count++;
  1306. X
  1307. X      for (i=0;! whitespace(buffer[i]); i++) ; 
  1308. X      buffer[i] = '\0';
  1309. X
  1310. X      /** now apply this pattern to all groups we've got, setting
  1311. X          the expire date as makes sense... **/
  1312. X
  1313. X      regular_expression = regcmp(buffer, (char *) 0);
  1314. X
  1315. X      for (i=0 ; i < group_count; i++)
  1316. X        if (matches(regular_expression, groups[i].name)) {
  1317. X          groups[i].unread_expire = unread_expire;
  1318. X          groups[i].read_expire = read_expire;
  1319. X        }
  1320. X    }
  1321. X
  1322. X    (void) fclose(fd);
  1323. X
  1324. X    if (verbose)
  1325. X     (void) printf("Checked against %d pattern%s in default-expire file.\n",
  1326. X         count, plural(count)); 
  1327. X}
  1328. X#endif
  1329. X
  1330. Xcheck_each_user()
  1331. X{
  1332. X    /** this routine goes through the /etc/passwd file to
  1333. X        find all the users on the machine.  For each entry
  1334. X        found, it will ascertain if they have a login shell
  1335. X        then look for a .newsrc file.  If they have one, it
  1336. X        will extract all the groups that they currently read,
  1337. X        marking each in memory as being read ..
  1338. X    **/
  1339. X
  1340. X    FILE   *fd;
  1341. X    struct passwd    *getpwent(), *pass;
  1342. X    char   newsrc[SLEN], buffer[SLEN], user_list[SLEN];
  1343. X    register int i;
  1344. X
  1345. X    /** initialize **/
  1346. X
  1347. X    user_list[0] = '\0';
  1348. X
  1349. X    /** and step through the password file .. **/
  1350. X
  1351. X    while ((pass = getpwent()) != NULL) {
  1352. X      /*if (has_login_shell(pass->pw_shell)) { */
  1353. X
  1354. X        if (pass->pw_uid == ROOT_UID && ! include_root)
  1355. X          continue;
  1356. X
  1357. X        (void) sprintf(newsrc, "%s/%s", pass->pw_dir, NEWSRC);
  1358. X        
  1359. X        if ((fd = fopen(newsrc, "r")) == NULL) continue;
  1360. X
  1361. X        if (verbose)
  1362. X          (void) printf("Checking against %s for user \"%s\"\n", 
  1363. X             NEWSRC, pass->pw_name);
  1364. X        else {
  1365. X          if (user_list[0] != '\0') (void) strcat(user_list, " ");
  1366. X          (void) strcat(user_list, pass->pw_name);
  1367. X        }
  1368. X
  1369. X        while (fgets(buffer, SLEN, fd) != NULL)
  1370. X          if (strchr(buffer, COLON) != (char *) NULL) {
  1371. X            for (i=0;buffer[i] != COLON; i++);
  1372. X        buffer[i] = '\0';
  1373. X            mark_as_read(buffer);
  1374. X          } 
  1375. X
  1376. X        (void) fclose(fd);
  1377. X      /*}*/
  1378. X    }
  1379. X
  1380. X    if (verbose && strlen(user_list) > 0) 
  1381. X      (void) fprintf(stderr, 
  1382. X          "Checked against \"%s\" for the following users:\n\t%s\n",
  1383. X          NEWSRC, user_list);
  1384. X}
  1385. X
  1386. X#ifndef CNEWS
  1387. Xsort_groups_by_expiration()
  1388. X{
  1389. X    /** We now resort the list according to the expiration date of
  1390. X        the group... 
  1391. X    **/
  1392. X
  1393. X    int compare_expirations();
  1394. X
  1395. X    qsort(groups, (unsigned) group_count, sizeof (struct group_rec), 
  1396. X          compare_expirations);
  1397. X}
  1398. X#endif
  1399. X
  1400. Xoutput_script()
  1401. X{
  1402. X    /** Now that we've gotten the groups sorted by their
  1403. X        expiration date, we can output a script that is suitable 
  1404. X        for input to the real netnews expire() program...
  1405. X    **/
  1406. X    
  1407. X    register int i; 
  1408. X#ifndef CNEWS
  1409. X    int current_expire_time = 0, expire, 
  1410. X        groups_on_line = 0, on_line = 0, in_expiration = 0;
  1411. X
  1412. X    /** set the current expiration time, then:
  1413. X          for each group that has the same date
  1414. X          output the group name
  1415. X        when we hit a new date output the new format line
  1416. X    **/
  1417. X
  1418. X    for (i=0; i < group_count; i++) {
  1419. X
  1420. X      /** set the expiration time based on if the group is 
  1421. X          currently being read or not... 
  1422. X      **/
  1423. X
  1424. X      expire = groups[i].is_read ? groups[i].read_expire : 
  1425. X             groups[i].unread_expire;
  1426. X
  1427. X      if (output_one_per_line) {
  1428. X        if (expire > max_history_expire)
  1429. X           (void) printf("%s -e %d -E %d -n %s\n", 
  1430. X              expire_cmd, expire, expire, groups[i].name);
  1431. X         else if (expire < min_history_expire)
  1432. X           (void) printf("%s -e %d -E %d -n %s\n", 
  1433. X              expire_cmd, expire, default_history_expire, 
  1434. X              groups[i].name);
  1435. X        else
  1436. X           (void) printf("%s -e %d -n %s\n", 
  1437. X              expire_cmd, expire, groups[i].name);
  1438. X      }
  1439. X      else {
  1440. X        if ( expire != current_expire_time || 
  1441. X         in_expiration > groups_per_cmd) {
  1442. X          if (expire > max_history_expire)
  1443. X            (void) printf("\n%s -e %d -E %d -n ", 
  1444. X                  expire_cmd, expire, expire);
  1445. X           else if (expire < min_history_expire)
  1446. X            (void) printf("\n%s -e %d -E %d -n ", 
  1447. X                  expire_cmd, expire, default_history_expire);
  1448. X          else
  1449. X            (void) printf("\n%s -e %d -n ", expire_cmd, expire);
  1450. X          groups_on_line = 0;
  1451. X          current_expire_time = expire;
  1452. X          in_expiration = 0;
  1453. X        }
  1454. X
  1455. X        in_expiration++;
  1456. X
  1457. X        on_line += strlen(groups[i].name) + 1;
  1458. X        
  1459. X        if (on_line > 66) {
  1460. X          (void) printf("%c \\\n\t", groups_on_line > 0? ',':' ');
  1461. X          on_line = 8 + strlen(groups[i].name);
  1462. X          groups_on_line = 0;
  1463. X        }
  1464. X
  1465. X        if (groups_on_line)
  1466. X          (void) printf("%c%s", comma_separated? ',' : ' ', groups[i].name);
  1467. X        else
  1468. X          (void) printf("%s", groups[i].name);
  1469. X
  1470. X        groups_on_line++;
  1471. X      }
  1472. X    }
  1473. X    (void) printf("\n");
  1474. X#else
  1475. X    for (i=0; i < group_count; i++) {
  1476. X
  1477. X      /** set the expiration time based on if the group is 
  1478. X          currently being read or not... 
  1479. X      **/
  1480. X
  1481. X      if (groups[i].is_read)
  1482. X           (void) printf("%s\tx\t%g-%g-%g\t-\n",groups[i].name, read_retention_period, read_expirey_period, read_purge_period);
  1483. X      else
  1484. X           (void) printf("%s\tx\t%g-%g-%g\t-\n",groups[i].name, unread_retention_period, unread_expirey_period, unread_purge_period);
  1485. X    }
  1486. X#endif
  1487. X}
  1488. X
  1489. Xint
  1490. Xcompare(a,b)
  1491. Xstruct group_rec *a, *b;
  1492. X{
  1493. X    /** strcmp() routine for our data structure, rather than the
  1494. X        simple expedient of just using strcmp directly.  See the
  1495. X        invocation of qsort() above
  1496. X    **/
  1497. X
  1498. X    return( strcmp(a->name, b->name) );
  1499. X}
  1500. X
  1501. X#ifndef CNEWS
  1502. Xint 
  1503. Xcompare_expirations(a, b)
  1504. Xstruct group_rec *a, *b;
  1505. X{
  1506. X    /** strcmp() routine for data for second sort -- this one
  1507. X        is a sort by the expiration date of the groups.  To
  1508. X        do this we want to look at the is_read flag and from
  1509. X        that decide which of the two expiration dates we want to be 
  1510. X        looking at.
  1511. X    **/
  1512. X
  1513. X    return ( (b->is_read ? b->read_expire : b->unread_expire) - 
  1514. X         (a->is_read ? a->read_expire : a->unread_expire) );
  1515. X}
  1516. X#endif
  1517. Xint
  1518. Xhas_login_shell(shell_name)
  1519. Xchar *shell_name;
  1520. X{
  1521. X    /** returns TRUE iff the shell given is contained in the
  1522. X        list of possible login shells compiled with.
  1523. X    **/
  1524. X
  1525. X    register int i;
  1526. X
  1527. X    for (i=0; login_shells[i][0] != '\0'; i++)
  1528. X      if (strcmp(login_shells[i], shell_name) == 0) return(TRUE);
  1529. X    
  1530. X    return(FALSE);
  1531. X}
  1532. X      
  1533. Xmark_as_read(name)
  1534. Xchar *name;
  1535. X{
  1536. X    /** Mark the group specified as being read -- it's extracted
  1537. X        from a users .newsrc file.
  1538. X    **/
  1539. X
  1540. X    int index;
  1541. X
  1542. X    if ((index = find_group(name)) == -1)
  1543. X      (void) fprintf(stderr, 
  1544. X          "** Couldn't find group '%s' in internal tables?? **\n",
  1545. X          name);
  1546. X    else
  1547. X      groups[index].is_read = TRUE;
  1548. X}
  1549. X
  1550. Xint
  1551. Xfind_group(name)
  1552. Xchar *name;
  1553. X{
  1554. X    /** A binary search of the list to find the group - returns the
  1555. X        index into the 'groups' array of the group, or '-1' if not
  1556. X        in the list.
  1557. X     **/
  1558. X
  1559. X    register int first = 0, last, middle, difference;
  1560. X
  1561. X    last = group_count-1;
  1562. X
  1563. X    while (first <= last) {
  1564. X          middle = ((first+last) / 2);
  1565. X
  1566. X          difference = strcmp(name, groups[middle].name);
  1567. X
  1568. X          if (difference < 0)
  1569. X            last = middle - 1;
  1570. X          else if (difference == 0)
  1571. X            return(middle);
  1572. X          else
  1573. X            first = middle + 1;
  1574. X        }
  1575. X
  1576. X        return(-1);
  1577. X}
  1578. END_OF_FILE
  1579. if test 21446 -ne `wc -c <'pexpire.c'`; then
  1580.     echo shar: \"'pexpire.c'\" unpacked with wrong size!
  1581. fi
  1582. # end of 'pexpire.c'
  1583. fi
  1584. if test -f 'pexpire.defs' -a "${1}" != "-c" ; then 
  1585.   echo shar: Will not clobber existing file \"'pexpire.defs'\"
  1586. else
  1587. echo shar: Extracting \"'pexpire.defs'\" \(1087 characters\)
  1588. sed "s/^X//" >'pexpire.defs' <<'END_OF_FILE'
  1589. X#
  1590. X# This is the "pexpire" default expiration times file.  The format of this
  1591. X# file is:
  1592. X#
  1593. X#   <regular expression>    <+expire>     <-expire>
  1594. X#
  1595. X# where <+expire> is the expiration date for groups that are currently
  1596. X# read by people on this machine, <-expire> are for those that are unread,
  1597. X# and <regular expression> is any regular expression as per regexp(3c).
  1598. X#
  1599. X# It is recommended that you have ".*" as the first expression so that you
  1600. X# can set the default expiration for all groups.  The processing order of
  1601. X# this information is: 
  1602. X#      for each pattern read in this file:
  1603. X#        for each group in the active file:
  1604. X#          if the pattern matches, set the dates accordingly.
  1605. X#
  1606. X# this means that the patterns "^comp.*" and "source" in that order
  1607. X# would result in "comp.unix.sources" having the source expire times.
  1608. X#
  1609. X# NOTE: never lead an expression with an asterisk -- assume all patterns
  1610. X#       are unrooted, and use '^' to get them left rooted if you want to
  1611. X.*        14    1
  1612. X^comp.*        8    2
  1613. X^talk.*        2    1
  1614. X^soc.*        2    1
  1615. X^news.*        5    2
  1616. X^ba.*        2    1
  1617. X^ca.*        2    1
  1618. X^misc.*        5    1
  1619. X^sci.*        2    1
  1620. X^slo.*        2    1
  1621. END_OF_FILE
  1622. if test 1087 -ne `wc -c <'pexpire.defs'`; then
  1623.     echo shar: \"'pexpire.defs'\" unpacked with wrong size!
  1624. fi
  1625. # end of 'pexpire.defs'
  1626. fi
  1627. if test -f 'pexpire.h' -a "${1}" != "-c" ; then 
  1628.   echo shar: Will not clobber existing file \"'pexpire.h'\"
  1629. else
  1630. echo shar: Extracting \"'pexpire.h'\" \(4166 characters\)
  1631. sed "s/^X//" >'pexpire.h' <<'END_OF_FILE'
  1632. X/**                   pexpire.h                   **/
  1633. X
  1634. X/****************************************************************************
  1635. X  This set of defines are those that might need to be localized or otherwise 
  1636. X  customized for your local system and setting.                            
  1637. X ****************************************************************************/
  1638. X
  1639. X/** first off, where's your netnews active file?  It'd be a suprise if
  1640. X    it wasn't as indicated here, but you can change it if you want.
  1641. X**/
  1642. X#define ACTIVE_FILE    "/usr/lib/news/active"
  1643. X
  1644. X/** NEWSRC is simply the name of the file kept in users home directories **/
  1645. X#define NEWSRC        ".newsrc"
  1646. X
  1647. X
  1648. X
  1649. X
  1650. X#ifndef CNEWS
  1651. X/***********************/
  1652. X/***********************/
  1653. X/** define for Bnews **/
  1654. X/***********************/
  1655. X/***********************/
  1656. X
  1657. X/** Next, the pexpire program has a default set of rules
  1658. X    that can be applied to the set of groups to determine the expiration dates
  1659. X    either by top-level newsgroup (eg. "comp.*") or down to the 
  1660. X    specific group (eg. "comp.sys.hp").  Please see the expire man
  1661. X    page for more discussion of this file.
  1662. X**/
  1663. X
  1664. X#define EXPIRE_DEFAULTS    "/usr/lib/news/pexpire.defs"
  1665. X#endif
  1666. X
  1667. X
  1668. X/** Finally, this is the command used for expiration of news (bnews version).
  1669. X    Most likely it'll be located in the same directory as the active file
  1670. X    (see above).  If you're running a strange expire command you might want
  1671. X    to check to ensure it understands "-e", "-E" and "-n" flags... see the man
  1672. X    page for further details.
  1673. X**/
  1674. X
  1675. X#ifndef CNEWS
  1676. X#define EXPIRE         "/usr/lib/news/expire"
  1677. X
  1678. X/** the default history expire (bnews version) is the standard number of days
  1679. X    that an article is allowed to live in the history file -- regardless of how
  1680. X    long it is on the machine in actual text form.  (This is different so that
  1681. X    you don't get into looping trouble with very fast expires and multiple news
  1682. X    feeds).
  1683. X
  1684. X    The netnews source has HISTEXP and DFLTEXP in seconds, and for our
  1685. X    own use, we'll change those back into days ...
  1686. X**/
  1687. X
  1688. X#define DEFAULT_MAX_HISTORY_EXPIRE    (HISTEXP / DAYS)
  1689. X#define DEFAULT_MIN_HISTORY_EXPIRE    (DFLTEXP / DAYS)
  1690. X
  1691. X/** if a group is being expired at less than the default minimum history
  1692. X    exiration time (bnews version), then we want to ensure that we have the
  1693. X    default time rather than the one specific to the group.  That is, if we
  1694. X    have a group with a 1 day expire, we still want to keep the articles
  1695. X    in the history file for, say, 2 weeks...
  1696. X**/
  1697. X
  1698. X#define DEFAULT_HISTORY_EXPIRE        (HISTEXP / DAYS)
  1699. X
  1700. X/** next, if the program cannot find your pexpire.default file (bnews version),
  1701. X    it will us the next two settings as the default for groups that are being
  1702. X    subscribed to and those that are not.  Recommended that the unread
  1703. X    expire not be incredibly short here in case the daemon messes up one
  1704. X    night - you might come back and a major chunk of news is gone!  
  1705. X**/
  1706. X
  1707. X#define DEFAULT_READ_EXPIRE      7
  1708. X#define DEFAULT_UNREAD_EXPIRE      0
  1709. X
  1710. X/** finally, when the program outputs the commands for eventual shell
  1711. X    execution (bnews version), it tries to keep them in a format that the
  1712. X    netnews expire(UTIL) command can deal with.  One of the problems is that
  1713. X    it is possible to have all 400 - 500 groups expire at the same
  1714. X    time, and it's too much for a single invocation.  Instead, you can
  1715. X    fine tune this to be the largest value possible, but smaller than
  1716. X    the max limit of expire().
  1717. X**/
  1718. X
  1719. X#define DEFAULT_GROUPS_PER_LINE   30
  1720. X
  1721. X/**************  end of local customization for Bnews ******************/
  1722. X
  1723. X#define DAYS    (60L*60L*24L)
  1724. X#define WEEKS    (7*DAYS)
  1725. X#define DFLTEXP    2*WEEKS    /* default no. of seconds to expire in        */
  1726. X#define HISTEXP    4*WEEKS    /* default no. of seconds to forget in        */
  1727. X#else
  1728. X
  1729. X/***********************/
  1730. X/***********************/
  1731. X/** defines for Cnews **/
  1732. X/***********************/
  1733. X/***********************/
  1734. X
  1735. X/*
  1736. X**    read/unread default retention, purge, and expirey days
  1737. X*/
  1738. X#define READ_RETENTION_DEFAULT    14.0
  1739. X#define READ_PURGE_DEFAULT        14.0
  1740. X#define READ_EXPIREY_DEFAULT      14.0
  1741. X#define UNREAD_RETENTION_DEFAULT  1.0
  1742. X#define UNREAD_PURGE_DEFAULT      1.0
  1743. X#define UNREAD_EXPIREY_DEFAULT    1.0
  1744. X
  1745. X
  1746. X#endif
  1747. END_OF_FILE
  1748. if test 4166 -ne `wc -c <'pexpire.h'`; then
  1749.     echo shar: \"'pexpire.h'\" unpacked with wrong size!
  1750. fi
  1751. # end of 'pexpire.h'
  1752. fi
  1753. if test -f 'pexplist' -a "${1}" != "-c" ; then 
  1754.   echo shar: Will not clobber existing file \"'pexplist'\"
  1755. else
  1756. echo shar: Extracting \"'pexplist'\" \(389 characters\)
  1757. sed "s/^X//" >'pexplist' <<'END_OF_FILE'
  1758. X#
  1759. X# pexplist
  1760. X#
  1761. X# This file contains entries that override later defaults generated by pexpire.
  1762. X# See dopexpire for use and expire(8) for format.
  1763. X#
  1764. X
  1765. X# big non-tech groups held long enough for a long weekend
  1766. X#ca,ba,sci,rec,talk,soc,misc,alt    x    4-4-4    -
  1767. X
  1768. X# real noise gets thrown away fast
  1769. Xjunk,control            x    1-1-1    -
  1770. X
  1771. X# dump all maps ... dopexpire being run by uuhosts
  1772. Xcomp.mail.maps            x    0-0-0    -
  1773. END_OF_FILE
  1774. if test 389 -ne `wc -c <'pexplist'`; then
  1775.     echo shar: \"'pexplist'\" unpacked with wrong size!
  1776. fi
  1777. # end of 'pexplist'
  1778. fi
  1779. echo shar: End of archive 1 \(of 1\).
  1780. cp /dev/null ark1isdone
  1781. MISSING=""
  1782. for I in 1 ; do
  1783.     if test ! -f ark${I}isdone ; then
  1784.     MISSING="${MISSING} ${I}"
  1785.     fi
  1786. done
  1787. if test "${MISSING}" = "" ; then
  1788.     echo You have tne archive.
  1789.     rm -f ark[1-9]isdone
  1790. else
  1791.     echo You still need to unpack the following archives:
  1792.     echo "        " ${MISSING}
  1793. fi
  1794. ##  End of shell archive.
  1795. exit 0
  1796.  
  1797.